
package com.cloudinnov.task;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import com.cloudinnov.dao.InitDataBaseDao;
import com.cloudinnov.logic.CameraControlLogic;
import com.cloudinnov.utils.CommonUtils;
import com.cloudinnov.utils.EmergecyPhoneServer;
import com.cloudinnov.utils.FireAlarmServer;
import com.cloudinnov.utils.MultiThreadServer;
import com.cloudinnov.utils.PropertiesUtils;
import com.mysql.jdbc.Connection;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * @author chengning
 * @date 2016年2月25日下午7:00:57
 * @email ningcheng@cloudinnov.com
 * @remark 项目启动的时候初始化：数据库
 * @version
 */
public class ContextListener {
	private static final Logger LOG = LoggerFactory.getLogger(ContextListener.class);
	
	@Autowired
	private JedisPool redisPool;
	@Autowired
	private InitDataBaseDao initDataBaseDao;
	@Autowired
	private AmqpTemplate callTemplate;
	@Autowired
	private AmqpTemplate fireTemplate;
	@Autowired
	CameraControlLogic cameraControlLogic;
	
	private static final String RESOURCE_CODE = "RE";
	private static final String RESOURCE_NAME = "resources";
	private static final String ROLE_CODE = "RO";
	private static final String ROLE_NAME = "role";
	private static final String USER_CODE = "US";
	private static final String USER_NAME = "user";
	private static final String CUSTOMER_CODE = "CU";
	private static final String CUSTOMER_NAME = "customer";

	@SuppressWarnings("unused")
	private void initialize() throws NumberFormatException, Exception {
		new InitializeDataBaseThread().start();
		initTcpRevice();
		initEmergecyPhoneRevice();
		initFireCRERevice();
	}
	/**
	 * @remark 打开紧急电话数据接收程序
	 */
	public void initEmergecyPhoneRevice() {
		new Thread() {
			public void run() {
				EmergecyPhoneServer emercyPhoneServer = new EmergecyPhoneServer(callTemplate);
				emercyPhoneServer.startListen(PropertiesUtils.findPropertiesKey("emergencyCallServer.hostname"),
						Integer.parseInt(PropertiesUtils.findPropertiesKey("emergencyCallServer.port")));
			};
		}.start();
	}
	
	/**
	 * @remark 打开火灾告警系统数据接收服务
	 */
	public void initFireCRERevice() {
		new Thread() {
			public void run() {
				FireAlarmServer tcpServer = new FireAlarmServer(fireTemplate);
				tcpServer.startFireSystem(PropertiesUtils.findPropertiesKey("fireAlarmCRTServer.port"));
			}
		}.start();
	}
	
	public void initTcpRevice() {
		new Thread() {
			public void run() {
				try {
					new MultiThreadServer(Integer.parseInt(PropertiesUtils.findPropertiesKey("car.detector.tcp.port")))
							.service();
				} catch (IOException e) {
				    LOG.error("启动车检仪Server失败, e: {}", e);
				}
			};
		}.start();
	}
	
	/**
	 * 初始化所有大屏列表
	 * @Title: initTcpRevice
	 * @Description: TODO
	 * @return: void
	 * @throws IOException
	 */
	public void initAllScreen() {
		new Thread() {
			public void run() {
				cameraControlLogic.saveAllScreensByTwallCode(null);// 同步大屏列表
			};
		}.start();
	}

	class InitializeDataBaseThread extends Thread {
		private int count = 3;
		private String messgae;

		public String getMessgae() {
			return messgae;
		}
		public void setMessgae(String messgae) {
			this.messgae = messgae;
		}
		public void run() {
			while (count > 0) {
				Jedis redis = null;
				try {
					// 检查初始化数据是否存在
					initDataBaseDao.newDatabaseCheck();
					count = 0;
					break;
				} catch (DataAccessException e) {
					if (e.getCause() instanceof SQLException) {
						SQLException se = (SQLException) e.getCause();
						if ("42S02".equals(se.getSQLState())) {
							LOG.debug("检查数据库表不存在,需要执行初始化操作");
							// 检查数据不存在需要执行初始化操作
							String url = PropertiesUtils.findPropertiesKey("jdbc.url");
							String driver = PropertiesUtils.findPropertiesKey("jdbc.driverClass");
							String username = PropertiesUtils.findPropertiesKey("jdbc.user");
							String password = PropertiesUtils.findPropertiesKey("jdbc.password");
							Connection conn = null;
							try {
								Class.forName(driver).newInstance();
							 	conn = (Connection) DriverManager.getConnection(url, username, password);
								ScriptRunner runner = new ScriptRunner(conn);
								runner.setErrorLogWriter(null);
								runner.setLogWriter(null);
								runner.runScript((new InputStreamReader(
										CommonUtils.class.getClassLoader().getResourceAsStream("init.sql"), "UTF-8")));
							} catch (UnsupportedEncodingException e1) {
								LOG.error("initializeDataBase UnsupportedEncodingException ERROR \r\n", e);
								messgae = CommonUtils.ERROR_MSG;
							} catch (SQLException e1) {
								LOG.error("initializeDataBase SQLException ERROR \r\n", e1);
								messgae = CommonUtils.ERROR_MSG;
							} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e2) {
								LOG.error("initializeDataBase InstantiationException ERROR \r\n", e2);
								messgae = CommonUtils.ERROR_MSG;
							} finally {
								try {
									conn.close();
								} catch (SQLException e1) {
									LOG.error("initializeDataBase connClose ERROR \r\n", e1);
								}
							}
							List<String> codes = initDataBaseDao.selectInitCodes();
							redis = redisPool.getResource();
							redis.select(Integer.parseInt(PropertiesUtils.findPropertiesKey("redis.db.code")));
							for (String code : codes) {
								if (code.substring(0, 2).equals(RESOURCE_CODE)) {
									redis.sadd(RESOURCE_NAME, code);
								} else if (code.substring(0, 2).equals(ROLE_CODE)) {
									redis.sadd(ROLE_NAME, code);
								} else if (code.substring(0, 2).equals(USER_CODE)) {
									redis.sadd(USER_NAME, code);
								} else if (code.substring(0, 2).equals(CUSTOMER_CODE)) {
									redis.sadd(CUSTOMER_NAME, code);
								}
							}
							messgae = CommonUtils.SUCCESS_MSG;
						}
					}
				} finally {
					redisPool.returnResource(redis);
				}
			}
			count--;
		}
	}
}
